package net.butfly.bus.context;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import net.butfly.bus.TX;
import net.butfly.bus.util.TXUtils;

public abstract class Context implements Map<String, Serializable> {

	public static Context CURRENT = new ThreadLocalContext();

	/****************************************************/

	public enum Mode {
		ReplacingByCleaning, MergingWithNew, MergingOnlyAbsent;
	}

	public static Map<String, Serializable> toMap() {
		return CURRENT.innerToMap();
	}

	protected abstract Map<String, Serializable> innerToMap();

	public static void merge(Map<String, Serializable> src) {
		merge(src, Mode.MergingWithNew);
	}

	public static void merge(Map<String, Serializable> src, Mode mode) {
		if (src == null)
			return;
		switch (mode) {
		case ReplacingByCleaning:
			CURRENT.clear();
			CURRENT.putAll(src);
			return;
		case MergingWithNew:
			CURRENT.putAll(src);
			return;
		case MergingOnlyAbsent:
			for (Entry<String, Serializable> e : src.entrySet())
				CURRENT.putIfAbsent(e.getKey(), e.getValue());
			return;
		}
	}

	/****************************************************/
	public enum Key {
		FlowNo, TX, SourceAppID, SourceHost, UserID;
	}

	public static FlowNo flowNo() {
		return (FlowNo) CURRENT.get(Key.FlowNo.name());
	}

	public static String sourceAppID() {
		return (String) CURRENT.get(Key.SourceAppID.name());
	}

	public static String sourceHost() {
		return (String) CURRENT.get(Key.SourceHost.name());
	}

	public static TX tx() {
		return (TX) CURRENT.get(Key.TX.name());
	}

	public static String userID() {
		return (String) CURRENT.get(Key.UserID.name());
	}

	public static void flowNo(FlowNo flowNo) {
		CURRENT.put(Key.FlowNo.name(), flowNo);
	}

	public static void sourceAppID(String sourceAppID) {
		CURRENT.put(Key.SourceAppID.name(), sourceAppID);
	}

	public static void sourceHost(String sourceHost) {
		CURRENT.put(Key.SourceHost.name(), sourceHost);
	}

	public static void tx(TX tx) {
		CURRENT.put(Key.TX.name(), (TXUtils.TXImpl) TXUtils.TXImpl(tx));
	}

	public static void userID(String userID) {
		CURRENT.put(Key.UserID.name(), userID);
	}

	public static Map<String, String> serialize(Map<String, Serializable> src) {
		Map<String, String> dst = new HashMap<String, String>();
		for (String key : src.keySet())
			dst.put(key, src.get(key).toString());
		return dst;
	}

	public static Map<String, Serializable> deserialize(Map<String, String> src) {
		Map<String, Serializable> dst = new HashMap<String, Serializable>();
		for (String key : src.keySet()) {
			try {
				switch (Key.valueOf(key)) {
				case FlowNo:
					dst.put(key, new FlowNo(src.get(key)));
					continue;
				case TX:
					dst.put(key, new TXUtils.TXImpl(src.get(key)));
					continue;
				default:
					dst.put(key, src.get(key).toString());
					continue;
				}
			} catch (IllegalArgumentException ex) {
				dst.put(key, src.get(key).toString());
			}
			dst.put(key, src.get(key).toString());
		}
		return dst;
	}
}
